#include "logger.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <dirent.h>
#include <sys/stat.h>

static FILE *log_fp = NULL;
static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;

// 创建文件夹的函数
static int createDirectory(const char *path)
{
    struct stat st = {0};
    if (stat(path, &st) == -1)
    {
        if (mkdir(path, 0777) == -1)
        {
            return -1;
        }
    }
    return 0;
}

// 获取当前时间戳
static void getTimeStamp(char *buffer, size_t size)
{
    time_t now = time(NULL);
    struct tm *tm_info = localtime(&now);
    strftime(buffer, size, "%Y-%m-%d %H:%M:%S", tm_info);
}

// 获取当前线程的LWP（轻量级进程ID）
static pid_t getThreadId()
{
    return syscall(SYS_gettid);
}

// 归档旧日志文件
static void archiveLogFile(const char *log_file)
{
    char dir_path[strlen(log_file) + 1];
    strcpy(dir_path, log_file);
    char *last_slash = strrchr(dir_path, '/');
    if (last_slash != NULL)
    {
        *last_slash = '\0'; // 截断路径至文件夹部分
    }

    char archived_name[256];
    time_t now = time(NULL);
    struct tm *tm_info = localtime(&now);
    strftime(archived_name, sizeof(archived_name), "server.log.%Y%m%d%H%M%S", tm_info);

    char archived_log_path[512];
    sprintf(archived_log_path, "%s/%s", dir_path, archived_name);
    rename(log_file, archived_log_path);
}

// 打包并压缩最近五次的日志文件，
static void manageLogArchives(const char *log_path)
{
    struct dirent *entry;
    DIR *dp = opendir(log_path);
    if (dp == NULL)
    {
        perror("opendir");
        return;
    }

    char *log_files[MAX_LOG_FILES + 1] = {NULL};
    int count = 0;
    while ((entry = readdir(dp)) != NULL)
    {
        if (strncmp(entry->d_name, "server.log.", 11) == 0 && strstr(entry->d_name, ".gz") == NULL)
        {
            log_files[count] = strdup(entry->d_name);
            count++;
        }
    }
    closedir(dp);

    // 如果日志文件数量大于等于5个，则打包压缩
    if (count >= MAX_LOG_FILES)
    {
        char archive_command[512];
        snprintf(archive_command, sizeof(archive_command), "tar -czf %s/logs_%ld.tar.gz %s/*.log.*", log_path, time(NULL), log_path);
        system(archive_command);

        for (int i = 0; i < count; i++)
        {
            if (log_files[i] != NULL)
            {
                char full_file[512];
                snprintf(full_file, sizeof(full_file), "%s/%s", log_path, log_files[i]);
                remove(full_file);
                free(log_files[i]);
            }
        }
    }
}

void initLog(const char *log_file)
{
    pthread_mutex_lock(&log_mutex);
    // 获取日志文件夹路径
    char dir_path[strlen(log_file) + 1];
    strcpy(dir_path, log_file);
    char *last_slash = strrchr(dir_path, '/');
    if (last_slash != NULL)
    {
        *last_slash = '\0';
    }
    // 创建日志文件夹
    if (createDirectory(dir_path) == -1)
    {
        fprintf(stderr, "Failed to create directory: %s\n", dir_path);
        exit(EXIT_FAILURE);
    }

    if (access(log_file, F_OK) == 0)
    {
        archiveLogFile(log_file);
    }
    manageLogArchives(dir_path);

    // 打开日志文件
    if (log_fp == NULL)
    {
        log_fp = fopen(log_file, "a");
    }

    pthread_mutex_unlock(&log_mutex);

    logMessage(LOG_LEVEL_INFO, __func__, "Logger", "Logger system initialized!");
}

// 记录日志
void logMessage(LogLevel_t level, const char *func, const char *module, const char *format, ...)
{
    if (log_fp == NULL)
    {
        return;
    }

    const char *log_level = NULL;
    switch (level)
    {
    case LOG_LEVEL_INFO:
        log_level = "INFO";
        break;
    case LOG_LEVEL_WARNING:
        log_level = "WARNING";
        break;
    case LOG_LEVEL_ERROR:
        log_level = "ERROR";
        break;
    case LOG_LEVEL_DEBUG:
        log_level = "DEBUG";
        break;
    }

    char timestamp[20];
    getTimeStamp(timestamp, sizeof(timestamp));

    pthread_mutex_lock(&log_mutex);

#ifndef USE_LWP_ID
    pthread_t thread_id = pthread_self();
    fprintf(log_fp, "[%s] [%s] [Thread-%lu] [%s] %s():", timestamp, log_level, (unsigned long)thread_id, module, func);
#else
    pid_t thread_pid = getThreadId();
    fprintf(log_fp, "[%s] [%s] [Thread-%d] [%s] %s(): ", timestamp, log_level, thread_pid, module, func);
#endif

    va_list args;
    va_start(args, format);
    vfprintf(log_fp, format, args);
    va_end(args);

    fprintf(log_fp, "\n");
    fflush(log_fp);

    pthread_mutex_unlock(&log_mutex);
}

// 关闭日志系统
void closeLog()
{
    logMessage(LOG_LEVEL_INFO, __func__, "Logger", "Logger system closed");
    logMessage(LOG_LEVEL_INFO, __func__, "Logger", "Server will be stopped...");
    pthread_mutex_lock(&log_mutex);
    if (log_fp != NULL)
    {
        fclose(log_fp);
        log_fp = NULL;
    }
    pthread_mutex_unlock(&log_mutex);
}
